﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Input;
using System.Xml;
using System.Xml.Linq;
using System.Linq;
using System.Windows.Media;

namespace SilverlightBase
{
	public partial class Page : UserControl
	{
		// Use for development to access remote site
		// Sop if you are testing against http://test.test, then that should be your url
		// In production it should be blank = "".
		public string siteBasePath = "";

		// Private vars
		public string siteXml = "";
		public FontFamily font = new FontFamily("Verdana");
		public string selectedColour = "00AEA4";
		public int rootNodeId = 0;
		public int currentNodeId = 0;
		public int blogNodeId = 0;
		public int blogPostNodeId = 0;

		private Dictionary<int, string> siteImages = new Dictionary<int, string>();
		string nodeIds = "";

		public bool movieIsLoaded = true;
		public bool movieIsPlaying = false;

		public int[] pressedKeys = new int[2];


		public Page()
		{
			// Required to initialize variables
			InitializeComponent();

			// Request site XML
			WebClient clientSiteXml = new WebClient();
			clientSiteXml.DownloadStringCompleted += new DownloadStringCompletedEventHandler(clientSiteXml_Completed);
			clientSiteXml.DownloadStringAsync(new Uri(siteBasePath + "/xml.aspx", UriKind.RelativeOrAbsolute));
		}

		/// <summary>
		/// Handle Site xml response
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		public void clientSiteXml_Completed(object sender, DownloadStringCompletedEventArgs e)
		{
			// Add scrollbar
			Application.Current.Host.Content.Resized += new EventHandler(Classes.Scroll.Events.Content_Resized);
			Classes.Scroll.SetupScroll();

			if (e.Error == null && e.Result != "")
			{
				siteXml = e.Result;

				if (currentNodeId == 0)
				{
					// Read Xml
					System.IO.TextReader textReader = new System.IO.StringReader(siteXml);
					XElement siteXmlDoc = XElement.Load(textReader);

					// Set selected colour
					selectedColour = (from node in siteXmlDoc.Descendants()
									  where (string)node.Attribute("alias") == "silverlightSelectedColor"
									  select (string)node.Value).Min();

					// Get images
					var images = from node in siteXmlDoc.Descendants()
								 where (string)node.Attribute("alias") == "silverlightBackgroundImage" || (string)node.Attribute("alias") == "silverlightLogoImage"
								 select node.Value;

					foreach (string image in images)
					{
						if (image != null && image != "" && image != "0")
						{
							if (!siteImages.ContainsKey(image.ToInt32()))
							{
								siteImages.Add(image.ToInt32(), "");

								if (nodeIds == "")
									nodeIds += image.ToString();
								else
									nodeIds += "," + image.ToString();
							}
						}
					}

					// Request image urls
					WebClient clientSiteImages = new WebClient();
					clientSiteImages.DownloadStringCompleted += new DownloadStringCompletedEventHandler(clientSiteImages_Completed);
					clientSiteImages.DownloadStringAsync(new Uri(siteBasePath + "/get-media-url.aspx?nodeId=" + nodeIds, UriKind.RelativeOrAbsolute));
				}
				else
				{
					// Get dispatcher thread and render page
					this.Dispatcher.BeginInvoke(delegate()
					{
						SetupPage(currentNodeId);
					});
				}
			}
			else
				Error();
		}

		/// <summary>
		/// Handle image response
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void clientSiteImages_Completed(object sender, DownloadStringCompletedEventArgs e)
		{
			if (e.Error == null)
			{
				// Add images to image arrays
				string[] imageUrls = e.Result.Split(Convert.ToChar(","));
				string[] imageNodeIds = nodeIds.Split(Convert.ToChar(","));

				for (int i = 0; i < imageNodeIds.Length; i++)
				{
					if (imageUrls[i] != "")
						siteImages[imageNodeIds[i].ToInt32()] = imageUrls[i];
				}

				// Setup site
				SetupSite();
			}
			else
				Error();
		}

		/// <summary>
		/// Setup core site elements
		/// </summary>
		private void SetupSite()
		{
			if (siteXml != "error" && siteXml != "")
			{
				// Get xml reader
				System.IO.TextReader textReader = new System.IO.StringReader(siteXml);
				XElement siteXmlDoc = XElement.Load(textReader);

				// Setup images
				Classes.Images.SetupDefaultImages(siteXml, siteImages);

				// Set default colour
				byte[] b = Library.HexToData(selectedColour);
				System.Windows.Media.SolidColorBrush mySolidColorBrush = new System.Windows.Media.SolidColorBrush();
				mySolidColorBrush.Color = System.Windows.Media.Color.FromArgb(255, b[0], b[1], b[2]);

				// Update control colour
				searchText.Foreground = mySolidColorBrush;

				// Set currentPage and rootNode
				currentNodeId = (from node in siteXmlDoc.Descendants("node") where node.Attribute("nodeTypeAlias").Value == "Frontpage" select (int)node.Attribute("id")).Min();
				rootNodeId = (from node in siteXmlDoc.Descendants("node") where node.Attribute("nodeTypeAlias").Value == "Data" select (int)node.Attribute("id")).Min();

				// Set Logo link
				Logo.Tag = currentNodeId.ToString();

				// Set blog nodes
				try
				{
					blogNodeId = (from node in siteXmlDoc.Descendants("node") where node.Attribute("nodeTypeAlias").Value == "Blog" select (int)node.Attribute("id")).Min();
				}
				catch
				{
				}

				// Set blog comment nodes
				try
				{
					blogPostNodeId = (from node in siteXmlDoc.Descendants("node") where node.Attribute("nodeTypeAlias").Value == "Post Comment" select (int)node.Attribute("id")).Min();
				}
				catch
				{
				}

				// Close 
				textReader.Close();

				// Show silverlight page
				LayoutRoot.Visibility = Visibility.Visible;
				LayoutRoot.UpdateLayout();

				// Setup search
				searchText.MouseLeftButtonUp += new MouseButtonEventHandler(Classes.Search.Events.SearchBtn_MouseLeftButtonUp);
				searchBtn.MouseLeftButtonUp += new MouseButtonEventHandler(Classes.Search.Events.SearchBtn_MouseLeftButtonUp);
				searchTxt.KeyDown += new KeyEventHandler(Classes.Search.Events.SearchTxt_KeyDown);

				//Setup page
				SetupPage(rootNodeId);
			}
			else
				Error();
		}

		/// <summary>
		/// Setup a page
		/// </summary>
		/// <param name="nodeId"></param>
		public void SetupPage(int nodeId)
		{
			// Remove elements in CommentGrid
			CommentGrid.Children.Clear();
			CommentGrid.UpdateLayout();

			// Read xml
			System.IO.TextReader textReader = new System.IO.StringReader(siteXml);
			XElement siteXmlDoc = XElement.Load(textReader);

			// Test if it the blog page, and get the first blog node
			if (nodeId == blogNodeId)
			{
				nodeId = (from node in siteXmlDoc.Descendants("node") where node.Parent.Attribute("id").Value == blogNodeId.ToString() select (int)node.Attribute("id")).Max();
			}

			// Create empty canvas and control element to stip namespace when attaching as child
			Canvas root = null;
			UIElement realRoot = null;

			// Set current page
			currentNodeId = nodeId;

			// Bind menu
			Classes.Menu.BindMenu(currentNodeId, rootNodeId);

			// Remove elements in Child grid
			ContentGrid.Children.Clear();

			// Get date
			List<List<string>> dataItems = new List<List<string>>();

			dataItems = (from dataItem in siteXmlDoc.Descendants("data")
						 where dataItem.Parent.Attribute("id").Value == currentNodeId.ToString()
						 select new List<string> { dataItem.Attribute("alias").Value, dataItem.Value }).ToList();

			string teaserNodeID = (from node in siteXmlDoc.Descendants("data")
								   where node.Parent.Attribute("id").Value == currentNodeId.ToString() && node.Attribute("alias").Value == "teaserNode"
								   select (string)node.Value).Min();

			string nodeType = (from node in siteXmlDoc.Descendants("node")
							   where node.Attribute("id").Value == currentNodeId.ToString()
							   select (string)node.Attribute("nodeTypeAlias").Value).Min();


			// Set content width
			Classes.Xaml.Content.contentWidth contentWidth = Classes.Xaml.Content.contentWidth.Full;

			// Add teaser if exist
			if (teaserNodeID != "" && teaserNodeID != null && teaserNodeID != "0")
			{
				// Set content width
				contentWidth = Classes.Xaml.Content.contentWidth.Small;

				// Get teaser
				string teaserText = (from node in siteXmlDoc.Descendants("data")
									 where node.Parent.Attribute("id").Value == teaserNodeID.ToString() && node.Attribute("alias").Value == "teaserText"
									 select (string)node.Value).Min();

				string teaserHeadline = (from node in siteXmlDoc.Descendants("data")
										 where node.Parent.Attribute("id").Value == teaserNodeID.ToString() && node.Attribute("alias").Value == "headline"
										 select (string)node.Value).Min();

				// Create teaser and strip namespace
				root = (Canvas)System.Windows.Markup.XamlReader.Load("<Canvas xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" + Classes.Xaml.Content.GetMainContentXaml(Classes.Xaml.Content.contentType.Teaser, teaserHeadline, teaserText, selectedColour, Classes.Xaml.Content.contentWidth.Full, teaserNodeID.ToInt32()) + "</Canvas>");
				realRoot = root.Children[0];
				root.Children.Remove(realRoot);
				ContentGrid.Children.Add(realRoot);

				// Set headline
				if (teaserHeadline.Length > 18)
					((TextBlock)ContentGrid.FindName("TeaserHeadline")).Text = teaserHeadline.Substring(0, 18) + "...";
				else
					((TextBlock)ContentGrid.FindName("TeaserHeadline")).Text = teaserHeadline;

				// Create html textBlock, since we can not load it using the XamlReader
				_3party.HtmlTextBlock teaserTextBox = new _3party.HtmlTextBlock();
				teaserTextBox.FontFamily = font;
				teaserTextBox.FontSize = 10;
				teaserTextBox.HorizontalAlignment = HorizontalAlignment.Left;
				teaserTextBox.VerticalAlignment = VerticalAlignment.Top;
				teaserTextBox.Margin = new Thickness(0, 0, 0, 0);
				teaserTextBox.TextWrapping = TextWrapping.Wrap;
				teaserTextBox.Width = 175;
				teaserTextBox.Text = teaserText;

				// Add the html textBlock
				((Grid)ContentGrid.FindName("TeaserTextGrid")).Children.Add(teaserTextBox);
				((Canvas)ContentGrid.FindName("TeaserLink")).MouseLeftButtonUp += new MouseButtonEventHandler(PageLink_MouseLeftButtonUp);
			}

			// Vars for comments
			string headline = "";
			string content = "";
			string date = "";
			string author = "";
			string email = "";

			foreach (List<string> dataItem in dataItems)
			{
				switch (dataItem[0])
				{
					case "headline":
						headline = dataItem[1];
						break;

					case "bodyText":
						content = dataItem[1];
						break;

					case "date":
						date = dataItem[1];
						break;

					case "author":
						author = dataItem[1];
						break;

					case "authorEmail":
						email = dataItem[1];
						break;
				}
			}

			// Create main content and strip namespace
			root = (Canvas)System.Windows.Markup.XamlReader.Load("<Canvas xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" + Classes.Xaml.Content.GetMainContentXaml(Classes.Xaml.Content.contentType.Main, headline, content, selectedColour, contentWidth) + "</Canvas>");
			realRoot = root.Children[0];
			root.Children.Remove(realRoot);
			ContentGrid.Children.Add(realRoot);

			// Create html textBlock, since we can not load it using the XamlReader
			_3party.HtmlTextBlock textBox = new _3party.HtmlTextBlock();
			textBox.FontFamily = font;
			textBox.FontSize = 11;
			textBox.HorizontalAlignment = HorizontalAlignment.Left;
			textBox.VerticalAlignment = VerticalAlignment.Top;
			textBox.Margin = new Thickness(12, 36, 0, -420);
			textBox.TextWrapping = TextWrapping.Wrap;
			textBox.Width = ((int)contentWidth - 52);
			textBox.UseDomAsParser = true;
			textBox.Text = content;

			// Add html textBlock
			((Grid)ContentGrid.FindName("MainContentGrid")).Children.Add(textBox);

			// Handel blog entry
			if (nodeType == "Blog Entry")
			{
				// Set headline
				((TextBlock)ContentGrid.FindName("MainContentHeadline")).Text = date.Substring(0, 10) + ": " + headline + " (" + author + " - " + email + ")";

				// Create comment
				root = (Canvas)System.Windows.Markup.XamlReader.Load("<Canvas xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" + Classes.Xaml.Comment.AddCommentXaml() + "</Canvas>");
				realRoot = root.Children[0];
				root.Children.Remove(realRoot);
				ContentGrid.Children.Add(realRoot);

				// Add mouse events
				((Grid)CommentGrid.FindName("CommentAddButton")).MouseLeftButtonUp += new MouseButtonEventHandler(Classes.Comments.Events.CommentAdd_MouseLeftButtonUp);
				((TextBox)ContentGrid.FindName("CommentAddEmail")).KeyDown += new KeyEventHandler(Classes.Comments.Events.txtMail_KeyDown);

				// Render comments
				List<string> comments = new List<string>();

				comments = (from dataItem in siteXmlDoc.Descendants("node")
							where dataItem.Parent.Attribute("id").Value == currentNodeId.ToString()
							select dataItem.Attribute("id").Value).ToList();

				int topCommentStart = 915;

				foreach (string commentNode in comments)
				{
					// Render comment
					RenderComment(commentNode);

					((Grid)CommentGrid.FindName("CommentLayer" + commentNode)).Margin = new Thickness(142, topCommentStart, 0, 0);
					((Grid)CommentGrid.FindName("CommentButton" + commentNode)).Tag = commentNode;
					((Grid)CommentGrid.FindName("CommentButton" + commentNode)).MouseLeftButtonUp += new MouseButtonEventHandler(Classes.Comments.Events.CommentDisplayHide_MouseLeftButtonUp);
					topCommentStart += 64;
				}
			}
			else
				((TextBlock)ContentGrid.FindName("MainContentHeadline")).Text = headline;

			// Update layout
			((Grid)ContentGrid.FindName("MainContentGrid")).UpdateLayout();
			textBox.UpdateLayout();

			// Add Scroll if needed
			if (Convert.ToInt32(Math.Floor(((_3party.HtmlTextBlock)((Grid)ContentGrid.FindName("MainContentGrid")).Children[0]).ActualHeight)) > 450)
			{
				((Canvas)ContentGrid.FindName("ScrollbarThumb")).MouseLeftButtonDown += new MouseButtonEventHandler(Classes.Scroll.Events.ScrollBar_MouseLeftButtonDown);
				((Canvas)ContentGrid.FindName("ScrollbarThumb")).MouseLeftButtonUp += new MouseButtonEventHandler(Classes.Scroll.Events.ScrollBar_MouseLeftButtonUp);
				((Canvas)ContentGrid.FindName("ScrollbarThumb")).MouseMove += new MouseEventHandler(Classes.Scroll.Events.ScrollBar_MouseMove);
			}
			else
			{
				((Grid)ContentGrid.FindName("Scrollbar")).Visibility = Visibility.Collapsed;
			}

			// Get media
			string mediaId = (from node in siteXmlDoc.Descendants("data")
							  where node.Parent.Attribute("id").Value == currentNodeId.ToString() && node.Attribute("alias").Value == "media"
							  select (string)node.Value).Min();

			// Close reader
			textReader.Close();

			// Add media
			if (mediaId != "" && mediaId != null && mediaId != "0")
			{
				WebClient clientMedia = new WebClient();
				clientMedia.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Classes.Media.Events.ClientMedia_Completed);
				clientMedia.DownloadStringAsync(new Uri(siteBasePath + "/get-media-url.aspx?nodeId=" + mediaId, UriKind.RelativeOrAbsolute));
			}
		}

		/// <summary>
		/// Render a comment
		/// </summary>
		/// <param name="nodeId"></param>
		/// <param name="isSelected"></param>
		private void RenderComment(string nodeId)
		{
			// Read xml
			System.IO.TextReader textReader = new System.IO.StringReader(siteXml);
			XElement siteXmlDoc = XElement.Load(textReader);

			Canvas root = null;
			UIElement realRoot = null;

			// Get comment
			List<List<string>> comment = new List<List<string>>();
			comment = (from dataItem in siteXmlDoc.Descendants("data")
					   where dataItem.Parent.Attribute("id").Value == nodeId.ToString()
					   select new List<string> { dataItem.Attribute("alias").Value, dataItem.Value }).ToList();

			string headline = "";
			string content = "";
			string date = (from node in siteXmlDoc.Descendants("node")
						   where node.Attribute("id").Value == nodeId.ToString()
						   select (string)node.Attribute("createDate").Value).Min();

			string author = "";
			string email = "";

			foreach (List<string> commentItem in comment)
			{
				if (commentItem[0] == "headline")
					headline = commentItem[1];

				if (commentItem[0] == "bodyText")
					content = commentItem[1];

				if (commentItem[0] == "author")
					author = commentItem[1];

				if (commentItem[0] == "authorEmail")
					email = commentItem[1];
			}

			// Create comment and strip namespace
			root = (Canvas)System.Windows.Markup.XamlReader.Load("<Canvas xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" + Classes.Xaml.Content.GetMainContentXaml(Classes.Xaml.Content.contentType.BlogComment, "", "", selectedColour, Classes.Xaml.Content.contentWidth.Full, nodeId.ToInt32()) + "</Canvas>");
			realRoot = root.Children[0];
			root.Children.Remove(realRoot);
			CommentGrid.Children.Add(realRoot);

			// Set values
			((TextBlock)CommentGrid.FindName("CommentHeadline" + nodeId)).Text = date.Replace("T", " ") + ": " + headline + " (" + author + " - " + email + ")";
			((TextBlock)CommentGrid.FindName("CommentText" + nodeId)).Text = content.StripHtml();

			// Close reader
			textReader.Close();
		}

		/// <summary>
		/// Render page in link click
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void PageLink_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
		{
			try
			{
				SetupPage(Convert.ToInt32(((Canvas)sender).Tag));
			}
			catch
			{
				SetupPage(Convert.ToInt32(((Image)sender).Tag));
			}
		}

		/// <summary>
		/// Display error
		/// </summary>
		private void Error()
		{
			LayoutRoot.Children.Clear();
			LayoutRoot.Visibility = Visibility.Visible;

			TextBlock textBlock = new TextBlock();

			textBlock.Text = "An error occurred, please contact the administrator of the site.";

			LayoutRoot.Children.Add(textBlock);

		}
	}
}